Welcome back.
In this lecture we're going to be scripting the service that is going to handle placing batteries around
the basement that players can collect to increase the charge of their flashlight.
So let's go ahead and get started.
I'm first going to show you the different positions that we're going to place them in the basement.
Inside of our other stuff folder.
We have a folder in here called Battery Positions.
And these are just different points that we have inside of our basement that we're going to be spawning
batteries at.
So we'll put a model there.
The players can click that model, and it'll allow them to collect a battery and increase the charge
on their flashlight.
So inside of service script service inside of the server folder, we're going to go ahead and open up
our battery service.
And inside of here we're going to need some services.
One is replicated storage.
Another service we'll need is server storage.
We will need the sound service.
And then we're also going to need a server script service.
Next, we can go ahead and create the table that will represent the service.
So we'll call it battery service.
I'll make sure to return that at the end of our script.
And we're also going to be using the service to act as a class.
So when we spawn these different battery instances around the map, we're going to use a constructor
that will create our battery object and we'll connect to that battery givers, click event and give
that player, you know, batteries when they click it and stuff like that.
So we'll have a battery service meta table in here and set the battery service meta table dot underscore
underscore index meta method equal to itself.
We'll have a reference to the game comms event and replicated storage, dot events, dot remotes, dot
game communication.
And then we'll also get the game comms enum.
So we'll require for replicated storage, dot modules, dot enums, game communication.
We're also going to get our anti-cheat module script inside of server script service.
That server modules anti-cheat.
And now we're going to make a reference to this battery giver, which is inside of server storage.
So we can call it example battery.
And it's inside of server stores.
Other stuff.
Dot battery.
So the plan is.
We're going to take this battery and I'll drag it here into the workspace so we can take a look at it.
And this battery is going to be randomly placed at these different positions along our map.
It has a slight glow to it.
So players are able to see it in the dark.
If they run out of flashlight batteries.
And they'll click this part to go ahead and collect the battery.
And then we'll make this disappear.
And then after like let's say 50s, we can make it respawn again.
So that way there isn't a finite number of batteries in the basement.
This is a very simple model.
All it has is the battery with a point light inside of it, and then it also has the quick part that
we're going to use the click detector inside of to listen for when this gets clicked.
So we can go ahead and move this back into the other stuff folder.
And we're also going to get all of the different battery positions inside of the basement.
So server storage, the other stuff.
Battery positions.
We're going to get all of the children.
And then we're also going to refer to a sound in the sound service called the collect sound.
And we'll play this to a player when they collect a battery.
So inside of SFX there's a sound called battery collected.
So when they collect a battery we're going to play this sound right here.
Perfect.
And then we can go ahead and create the table to act as cache for storing all of the current battery
objects.
So current batteries is equal to a table.
We're going to need a random data type.
And then we're going to need some constants.
So we'll need a constant to define the respawn cooldown, and we'll set that to like 50s.
We're going to have a constant to represent how much charge we should give to a player when they click
one of those batteries, so we can call it battery value, and we could do something like 20.
So if the flashlight's at like 40%, we'll add an extra 20 to make it 60%.
And then we're also going to define the click distance or how close the player needs to be in order
to click the giver.
And we'll make that ten studs.
Now we're going to need some private functions.
One function is going to be responsible for changing the battery givers visibility.
So when it gets clicked we want to make it not visible.
And then when it regenerates we want to make it visible again.
So this will get passed a model and then a boolean to tell it whether or not we'd like to make it visible
or invisible.
We're going to need a function that we're going to listen for when our different battery givers get
clicked.
So we'll call it on clicked.
We're going to need a function to actually spawn one of those battery givers on the map, and we'll
get a part passed to this function, which will act as the position we need to set this giver at.
And then we can finally have a function to actually go ahead and place all of our batteries on the map.
From this point we can create our constructor.
So batteries service dot new.
We'll just get past the battery model or the giver.
And then we're also going to need a start function for our battery service.
And this is what we will use to place all of our batteries randomly on the map.
So what this function is going to do is it's going to loop through every single part or position in
our battery positions table.
And we're going to spawn a battery at this position, and we'll have this function return back to us
the model of that battery giver.
So we'll get a model back from this.
And then we can use our constructor battery service.
Dot new and pass this model to that function.
So inside of the spawn battery function we're going to create a clone of our example battery giver.
So example battery clone.
And again we're going to use the pivot two function to pivot this to a new position.
And that position is going to be a C frame dot new.
We'll get the part dot position and subtract this by a vector three dot new zero.
On the x, we get the part size on the y axis divided by two, and then zero on the z axis.
And then we're going to add another vector three dot new.
And this is going to be zero on the x axis.
And then we're going to get our clone and get the extent size for the y axis.
And divide that by two and then pass zero for the z axis.
And then finally we're going to add a C frame angles zero on the x axis.
And then we're going to have a random rotation.
So RNG next integer -360 to 360 degrees.
And then we can go ahead and do zero on the z axis.
Once we set the c frame to the correct position, we're going to take our clone and set the parent equal
to the workspace dot krustikrab we can put in the basement and then inside of the batteries folder.
And then we can go ahead and return this clone or the giver.
Then we take this clone.
We pass it to our new constructor.
So what we're going to do in here is we're going to create a table called self.
Will make a property to refer to the battery model, which is equal to the battery model passed to the
function.
And we'll also make a reference to the click detector which is in the battery model.
Dot click part.
Dot click detector.
And then we can go ahead and listen to when our click detector is clicked.
And we can connect a lambda function to this and get the player that clicked it.
And then we can call our on clicked function.
We can pass the object itself to it, and then we can also pass the player who clicked it.
Then we can go ahead and set the meta table on our object with the battery service meta table.
We're going to insert this into our current batteries table, past self and then return self at the
end of our constructor.
And now we can go ahead and fill out our onClick function.
So we'll get self here.
And then the player who clicked our battery giver.
And when the player clicks it, we first want to check whether or not they actually have a flashlight
on them.
So we can get this flashlight from either the player's backpack, find first child and we can look for
a flashlight, or if they have it equipped, we can check their character as well.
So player dot character find first child flashlight.
If they do not have a flashlight for some reason, then we're just going to return.
Otherwise, we need to check whether or not the player cheated when trying to grab this battery.
So let's say they tried to click it from across the map by using like a spoofing technique.
Then again, we're going to check if this player cheated and get a message from our anti-cheat and check
player distance to object.
We're going to pass the player the self dot battery model dot click part.
And then we can also pass the click distance right there.
If this player cheated, then we're going to go ahead and kick this player and give them that message
and then just return.
Otherwise we can use our set, uh, battery visibility function and pass our model to this and allow
it to change the visibility or make our model disappear, and then make the model visible again after
a certain amount of time.
So we could pass to this function like false.
And this will change our battery model.
It'll disable the light and make it transparent.
So let's go ahead and fill that out here.
All we're going to do in this function is we're going to refer to the model.
And inside the model there is the battery part itself.
And we can set the transparency of it equal to 0 or 1 depending on the boolean.
So we could do bool and zero.
So if boolean is true then the transparency gets set to zero.
Otherwise the transparency gets set to one.
Again for the model click part dot click detector.
We're going to get the max activation distance and set this equal to.
If the bool is true, then we're going to set it equal to the click distance.
Otherwise we'll set it to zero.
So that way the players can't click it anymore.
And then for the model dot battery dot attachment inside of there is our point light.
We're going to set the enabled equal to the boolean pass to the function.
And that's all we're going to do for this.
After we make the battery invisible, what we could do next is get the new battery value that we're
going to set on the player's flashlight.
So we're going to use the math dot minimum function because we don't want to go above the flashlights
Max battery capacity.
So what we could pass here is we're going to get the flashlight get attribute.
Current battery.
And we're going to add.
Our battery value.
Now, if this number goes above 100, that's okay, because the other number we're going to pass here
is the flashlight get attribute max battery.
So just in case let's say there are batteries at 90.
And then they click a battery and get plus 20.
That means this will be 110.
And we don't want to go above the max battery.
So the math dot minimum will pick the smallest number, which in this case would be the max battery
attribute.
Afterwards, we can refer to the flashlight again and set the attribute on it.
Of current battery equal to this new battery value.
Then we can use the game comms event and fire it to this particular player to play a sound.
So game comms enum dot two client dot play sound.
And the sound is going to be equal to our collection sound, and then we can set play at point equal
to false.
From this point, we're going to use task dot delay to delay a function.
We're going to pass the respawn cooldown.
And the function we want to delay is our set battery visibility function.
And then to this function we have to pass the self dot battery model again.
And then we also need to pass a boolean.
In this case that's going to be true.
So after 50s we're going to make our battery model visible again and make it clickable again.
That way another player can come along and collect the battery off of it.
Now there is one small security vulnerability, and that is, even if we set the click distance to zero,
an exploiter could still spoof this click detector and fire it close by to it and collect the battery,
even though it's invisible or not ready to be used.
So a way we could stop that is, we could go back into our constructor and have a another property we
could call it something like is enabled, and we'll set that to true by default.
And then inside of the set battery function we can change inside of our object the is enabled property.
So that means instead to this function we should pass the object itself.
And we could also pass the model.
Why not.
So we'll do set battery visibility.
We'll pass self.
We'll pass the model.
And we'll make sure to do that down here as well.
And then we can get self inside of this function.
And set self dot is enabled equal to the boolean.
And then inside of our onClick function, what we could do is we could check if self dot is enabled
is not true.
So if not self dot is enabled, then we're just going to return because the battery is currently in
its cool down mode.
Perfect.
And I think that's all we need to do for our battery service.
So we can go ahead and test it out.
And unfortunately it looks like we immediately did get an error.
So inside of our service we got failed to start.
Uh, module C frame expected got vector three.
So let's go ahead and figure out what the problem is on line 69.
And the problem is, is that we forgot to actually place this vector three inside of the c frame2 because
as you can see, our C frame dot new function terminates right here.
And then we're attempting to add a vector three which causes the value to return a vector three.
So we need to copy this real quick.
And then we actually need to set this inside of here.
So we'll put an extra quotation and we'll put another one here.
So after our vector three function right here we can then paste our other vector three and then indent
that there.
And then after we set the c frame we're applying the rotation to it afterwards.
So now our problem should be fixed.
Let's go ahead and test this out again.
Okay, now we are inside of the basement.
We have our flashlight, and let's go ahead and drain some battery.
And let's go ahead and see if our battery spawned on the map.
So let's go ahead and look around and see if we can find any batteries anywhere we walk around.
Hopefully we can find one here soon.
And perfect.
Here's a battery right here laying on our shelf.
As you can see, you can kind of see it glowing here in the darkness.
And now that our battery is at 87, we should be able to click it.
And unfortunately nothing is happening when we are clicking our battery.
So let's go ahead and figure out why that is.
Alrighty.
And the reason why our on click function is actually not working is because of this condition.
Check right here.
We forgot to include a Not statement because we want to return when we do not have a flashlight, and
not when we do have a flashlight.
So hopefully that should have fixed our problem and we can go ahead and test out our story again.
Okay.
So let's go ahead and go look for our battery again.
And as we go up to it let's go ahead and click it and see what happens.
Perfect.
And just like that we played the sound and we got more battery added to our flashlight.
And as you can see, our battery is also no longer here.
And we can't click anything here.
We're going to have to wait for it to respond after 50s.
But let's go ahead and find another battery somewhere around our map.
Take a quick look around, see if we can find another battery.
Here we go.
Here's another battery.
If we go ahead and click this one, we get our nice battery added to our flashlight and we can keep
looking around.
And actually let's go ahead and go back and see when this battery right here responds.
So we'll wait a little bit.
And just like that, our battery respawn and we could go ahead and grab it and get more charge added
to our battery.
Very nice.
So that wraps up everything we needed to do for this lecture, and I'll go ahead and see you in the
next one.